package com.cx.base.day19_thread;

import java.math.BigDecimal;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @Author: robert.song
 * @Date: Created in 2021/8/31
 */
public class Thread_13_2_原子性_原子引用 {
    static AtomicReference<String> ref = new AtomicReference<>("A");

    public static void main(String[] args) {
        DecimalAccount decimalAccount = new DecimalAccountImpl(new BigDecimal(14.14444545));
        System.out.println("开始");

        // 创建一个可缓存线程池
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 300; i++) {

            cachedThreadPool.execute(new Runnable() {
                public void run() {
                    decimalAccount.withdraw(new BigDecimal(0.4444));
                }
            });
        }
    }

}

class DecimalAccountImpl implements DecimalAccount {
    private AtomicReference<BigDecimal> balance;

    public DecimalAccountImpl(BigDecimal bigDecimal) {
        this.balance = new AtomicReference<>(bigDecimal);
    }

    @Override
    public BigDecimal getBalance() {
        return balance.get();
    }

    @Override
    public void withdraw(BigDecimal amount) {
        if (balance.get().doubleValue() > 0) {
            boolean flag = true;
            while (flag) {
                BigDecimal prev = balance.get();
                BigDecimal next;
                if (prev.doubleValue() > amount.doubleValue()) {
                    next = prev.subtract(amount);
                    if (balance.compareAndSet(prev, next)) {
                        System.out.println(Thread.currentThread().getName() + "：" + "已扣余额：" + amount.doubleValue() + "，当前余额：" + next);
                        break;
                    }
                } else {
                    System.out.println(Thread.currentThread().getName() + "：" + "余额不足");
                    break;
                }
            }
        }

    }
}

interface DecimalAccount {
    //    获取余额
    BigDecimal getBalance();

    //    取款
    void withdraw(BigDecimal amount);


}
